package cn.com.bluemoon.daps.model.entity;

import cn.com.bluemoon.daps.common.domain.BaseModel;
import cn.com.bluemoon.daps.common.enums.DatabaseType;
import cn.com.bluemoon.daps.common.enums.SysWarehouseLevel;
import cn.com.bluemoon.daps.common.sql.IDbDataSource;
import cn.com.bluemoon.daps.common.validation.illegal.IllegalChar;
import cn.com.bluemoon.daps.model.dto.DapModelVersionInter;
import cn.com.bluemoon.daps.model.dto.DevImportCheck;
import com.baomidou.mybatisplus.annotation.EnumValue;
import com.baomidou.mybatisplus.annotation.TableField;
import com.google.common.base.Objects;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import org.apache.commons.lang3.StringUtils;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.LinkedHashMap;

/**
 * <p>
 * 数据模型-模型中设计表的表
 * 4.数据约束
 * <p>
 * 仅在模型所选系统分类是 数仓模型时， 才显示/允许编辑 层级、主题
 * <p>
 * 层级、主题选择后，根据前缀检查表命名是否符合规，,如选择 DWD/DWS/ADS/DIM 并选择 主题后，自动在增加表名的前缀，如 ： d_ec_ 、e_e
 * {@link 03.数据资产管理原型/新建表.html}
 * {@link DapDataModelSystemTagMiddle#getRelDataId()}
 * </p>
 * dap_data_model_table
 *
 * @author admin
 * @since 2020-08-03
 */
@Data
@Accessors
@ApiModel(value = "DapDataModelTable", description = "数据模型-模型中设计表的表")
public class DapDataModelTable extends BaseModel<DapDataModelTable>
        implements DapModelVersionInter, IDbDataSource {

    private static final long serialVersionUID = 1L;
    public static final LinkedHashMap<String, String> includeFieldAndDescMap = new LinkedHashMap<String, String>(){{
        put("engName","表英文名");
        put("name","表中文名");
    }};
    protected static final String[] includeFields = new String[]{"engName", "name", "hiveStoredAs", "hiveSerdeProps", "hiveExternal", "hiveLocation", "hiveTableProps"};

    @ApiModelProperty(value = "业务描述")
    @Size(max = 500, message = "业务描述不可以大于{max}")
    private String businessDesc;

    /**
     * 数仓分类
     * * 如果数据模型类型为{SysWarehouseLevel#getWarehouseSys()} eq {cn.com.bluemoon.dap.enums.SystemType#WAREHOUSE_SYS}
     * * 则必填
     * <strong>{DapSystemCategory#getId()}，本字段是针对数仓中的层级类型的分类</strong>
     */
    @ApiModelProperty(value = "数仓模型中对应的主题分类id")
    private String categoryId;

    @ApiModelProperty(value = "关联模型id")
    private String dataModelId;

    @ApiModelProperty(value = "数据源id")
    private String dataSourceId;

    @ApiModelProperty(value = "表英文名")
    @NotNull(message = "表英文名不允许为空")
    @Size(max = 64, message = "表英文名不可以大于{max}")
    @IllegalChar(name = "engName", message = "表名中存在非法字符")
    // @NoSqlKeyword(name = "engName", message = "表名不可为关键字")
    @NotNull(message = "表英文名不允许为空", groups = DevImportCheck.class)
    @Size(max = 64, message = "表英文名不可以大于{max}" , groups = DevImportCheck.class)
    private String engName;

    @ApiModelProperty(value = "表中文名")
    @NotNull(message = "表中文名不允许为空")
    @Size(max = 2048, message = "表中文名不可以大于{max}")
    @NotNull(message = "表中文名不允许为空", groups = DevImportCheck.class)
    @Size(max = 2048, message = "表中文名不可以大于{max}", groups = DevImportCheck.class)
    private String name;

    @ApiModelProperty(value = "表所属的schema")
    private String tableSchema;
    /**
     * 如果数据模型类型为{@link SysWarehouseLevel#getWarehouseSys()} eq {cn.com.bluemoon.dap.enums.SystemType#WAREHOUSE_SYS}
     * 则必填
     */
    @EnumValue
    @ApiModelProperty(value = "数仓模型中对应的层级类型：从1~5分别对应OD、DWD、DIM、DWS、ADS")
    @Deprecated
    private SysWarehouseLevel warehouseLevelType;

    @ApiModelProperty(value = "已发布版本的数据，记录模型下最新的唯一id，比如：最新表id,最新索引id ")
    private String pId;

    @ApiModelProperty(value = "标记当前数据是否为模型最新数据，null/0 为已发布数据、1为该模型下的最新数据")
    private Integer dataNewest;

    @ApiModelProperty(value = "表分类，1 表示维表，2 为事实表 3 贴源表")
    private Integer tableCategory;

    @ApiModelProperty("与warehouse_tb字段相关，对应当前分组父级id")
    private String groupPid;

    @ApiModelProperty("与warehouse_tb字段相关，对应当前分组id")
    private String groupId;

    @ApiModelProperty("表是否比上一次发布有变化")
    @TableField(exist = false)
    private Boolean change = Boolean.TRUE;

    @ApiModelProperty("1 数仓产品 0非数仓产品")
    private Boolean warehouseTb;

    @ApiModelProperty("hive表定义-数据存储格式：1: TEXTFILE, 2: SEQUENCEFILE, " +
            "3: ORC, 4: PARQUET, 5: AVRO, 6: RCFILE, 7: JSONFILE")
    private Integer hiveStoredAs;

    @ApiModelProperty("hive表定义serde文件的配置信息")
    private String hiveSerdeProps;

    @ApiModelProperty("hive表中，1为外部表 0为内部表")
    private Boolean hiveExternal = Boolean.FALSE;

    @ApiModelProperty("hive表文件存储路径（不包含协议头）")
    private String hiveLocation;

    @ApiModelProperty("hive表定义的配置信息")
    private String hiveTableProps;

    @ApiModelProperty(value = "是否注册数据服务，false：不注册 为空、true：注册，默认为空")
    private Boolean registerApi;

    @ApiModelProperty(value = "所属库名", hidden = true)
    @TableField(exist = false)
    private String dbName;

    @ApiModelProperty(value = "用于数据对比中多版本的关联键值", hidden = true)
    @TableField(exist = false)
    private String bmKey;

    @ApiModelProperty(value = "数据库类型，用于区分不同数据库，equals中mysql忽略大小写判断相等", hidden = true)
    @TableField(exist = false)
    private DatabaseType dbType;

    @ApiModelProperty(value = "标识该表是否为共享表，true是，false否", hidden = true)
    @TableField(exist = false)
    private Boolean shareTable;

    @ApiModelProperty(value = "组路径", hidden = true)
    @TableField(exist = false)
    private String groupPath;

    @ApiModelProperty(value = "是否入仓，true表示是 false表示空 默认为空")
    private Boolean dataWarehouse;

    @ApiModelProperty(value = "用于业务模型导入hive模型中，记录源表id")
    private String sourceTableId;

    public DapDataModelTable() {
        this.dbType = DatabaseType.MYSQL;
    }

    public DapDataModelTable(DatabaseType dbType) {
        this.dbType = dbType;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        DapDataModelTable that = (DapDataModelTable) o;
        if (DatabaseType.MYSQL.equals(dbType)){
            return StringUtils.equalsIgnoreCase(engName, that.engName) &&
                    Objects.equal(name, that.name) &&
                    Objects.equal(hiveStoredAs, that.hiveStoredAs) &&
                    Objects.equal(hiveSerdeProps, that.hiveSerdeProps) &&
                    Objects.equal(hiveExternal, that.hiveExternal) &&
                    Objects.equal(hiveLocation, that.hiveLocation) &&
                    Objects.equal(hiveTableProps, that.hiveTableProps);
        }
        return Objects.equal(engName, that.engName) && Objects.equal(name, that.name) && Objects.equal(hiveStoredAs, that.hiveStoredAs) && Objects.equal(hiveSerdeProps, that.hiveSerdeProps) && Objects.equal(hiveExternal, that.hiveExternal) && Objects.equal(hiveLocation, that.hiveLocation) && Objects.equal(hiveTableProps, that.hiveTableProps);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(engName, name, hiveStoredAs, hiveSerdeProps, hiveExternal, hiveLocation, hiveTableProps);
    }

    @Override
    public String[] sqlCompareFields() {
        return includeFields;
    }
}
